package org.abc.fund.service.factorService;

import lombok.RequiredArgsConstructor;
import org.abc.fund.entity.factorEntity.Factor;
import org.abc.fund.repository.factorRepository.FactorRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 因子管理服务
 */
@Service
@RequiredArgsConstructor
@Transactional
public class FactorService {
    
    private static final Logger log = LoggerFactory.getLogger(FactorService.class);
    
    private final FactorRepository factorRepository;
    private DataSourceIngestionHistoryService dataSourceIngestionHistoryService;

    
    /**
     * 创建因子
     */
    @CacheEvict(value = "factorCache", allEntries = true)
    public Factor createFactor(Factor factor) {
        // 检查因子代码是否已存在
        if (factorRepository.existsByFactorCode(factor.getFactorCode())) {
            throw new IllegalArgumentException("因子代码已存在: " + factor.getFactorCode());
        }
        
        factor.setCreateTime(LocalDateTime.now());
        factor.setUpdateTime(LocalDateTime.now());
        
        return factorRepository.save(factor);
    }
    
    /**
     * 更新因子
     */
    @CacheEvict(value = "factorCache", allEntries = true)
    public Factor updateFactor(Long id, Factor factor) {
        Factor existingFactor = factorRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("因子不存在: " + id));
        
        // 检查因子代码是否被其他因子使用
        if (!existingFactor.getFactorCode().equals(factor.getFactorCode()) &&
                factorRepository.existsByFactorCode(factor.getFactorCode())) {
            throw new IllegalArgumentException("因子代码已存在: " + factor.getFactorCode());
        }
        
        existingFactor.setFactorCode(factor.getFactorCode());
        existingFactor.setFactorName(factor.getFactorName());
        existingFactor.setDescription(factor.getDescription());
        existingFactor.setFactorType(factor.getFactorType());

        existingFactor.setEnabled(factor.getEnabled());
        existingFactor.setUpdateTime(LocalDateTime.now());
        existingFactor.setUpdatedBy(factor.getUpdatedBy());
        
        return factorRepository.save(existingFactor);
    }
    /**
     * 更新因子
     */
    public ResponseEntity<Factor> updateFactorByTime() {
        try {
            List<Factor> factorList=factorRepository.findByEnabled(true);
            LocalDate today = LocalDate.now();
            LocalDate oneMonthAgo = today.minusMonths(1);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String todayFormatted = today.format(formatter);
            String oneMonthAgoFormatted = oneMonthAgo.format(formatter);
            for (Factor factor : factorList) {
                List<Double> factorData=dataSourceIngestionHistoryService.getShowData(factor.getFundCode(),oneMonthAgoFormatted,todayFormatted);
                Factor factorToUpdate=new Factor();
                factorToUpdate.setFactorCode(factor.getFactorCode());
                factorToUpdate.setFactorName(factor.getFactorName());
                factorToUpdate.setDescription(factor.getDescription());
                factorToUpdate.setFactorType(factor.getFactorType());
                factorToUpdate.setEnabled(factor.getEnabled());
                switch (factor.getFactorName()) {
                    case"简单收益率因子":
                        factorToUpdate.setValue(factorData.get(0));
                        break;
                    case "年化收益率因子":
                        factorToUpdate.setValue(factorData.get(1));
                        break;
                    case "对数收益率因子":
                        factorToUpdate.setValue(factorData.get(2));
                        break;
                    case "波动率因子":
                        factorToUpdate.setValue(factorData.get(3));
                        break;
                    case "夏普比率因子":
                        factorToUpdate.setValue(factorData.get(4));
                        break;
                    case "最大回撤因子":
                        factorToUpdate.setValue(factorData.get(5));
                        break;
                    case "下行风险因子":
                        factorToUpdate.setValue(factorData.get(6));
                        break;
                    case"相对强弱指数因子":
                        factorToUpdate.setValue(factorData.get(7));
                        break;
                    case"移动平均值因子":
                        factorToUpdate.setValue(factorData.get(8));
                        break;
                    case"申购开放频率因子":
                        factorToUpdate.setValue(factorData.get(9));
                        break;
                    case"赎回开放频率因子":
                        factorToUpdate.setValue(factorData.get(10));
                        break;
                }
                factorToUpdate.setUpdateTime(LocalDateTime.now());
                factorToUpdate.setUpdatedBy(factor.getUpdatedBy());
                factorRepository.save(factorToUpdate);

            }
            return ResponseEntity.ok(factorList.get(0));
        } catch (Exception e) {

            return ResponseEntity.internalServerError().build();
        }
    }
    
    /**
     * 删除因子
     */
    public boolean deleteFactor(Long id) {
        try {
            Factor factor = factorRepository.findById(id)
                    .orElseThrow(() -> new IllegalArgumentException("因子不存在: " + id));
            factorRepository.delete(factor);
            return true;
        } catch (Exception e) {
            log.error("删除因子失败: {}", e.getMessage());
            return false;
        }
    }
    /**
     * 根据ID查找因子
     */
    @Transactional(readOnly = true)
    public Optional<Factor> findById(Long id) {
        return factorRepository.findById(id);
    }
    
    /**
     * 根据因子代码查找因子
     */
    @Transactional(readOnly = true)
    public Optional<Factor> findByFactorCode(String factorCode) {
        return factorRepository.findByFactorCode(factorCode);
    }
    
    /**
     * 分页查询因子
     */
    @Transactional(readOnly = true)
    public Page<Factor> findFactors(String factorName, String factorCode, String factorType, Boolean enabled, Pageable pageable) {
        if (factorName != null && !factorName.isEmpty()) {
            if (factorType != null && enabled != null) {
                return factorRepository.findByFactorNameContainingAndFactorTypeAndEnabled(factorName, factorType, enabled, pageable);
            } else if (factorType != null) {
                return factorRepository.findByFactorNameContainingAndFactorType(factorName, factorType, pageable);
            } else if (enabled != null) {
                return factorRepository.findByFactorNameContainingAndEnabled(factorName, enabled, pageable);
            } else {
                return factorRepository.findByFactorNameContaining(factorName, pageable);
            }
        } else if (factorCode != null && !factorCode.isEmpty()) {
            if (factorType != null && enabled != null) {
                return factorRepository.findByFactorCodeContainingAndFactorTypeAndEnabled(factorCode, factorType, enabled, pageable);
            } else if (factorType != null) {
                return factorRepository.findByFactorCodeContainingAndFactorType(factorCode, factorType, pageable);
            } else if (enabled != null) {
                return factorRepository.findByFactorCodeContainingAndEnabled(factorCode, enabled, pageable);
            } else {
                return factorRepository.findByFactorCodeContaining(factorCode, pageable);
            }
        } else if (factorType != null && enabled != null) {
            return factorRepository.findByFactorTypeAndEnabled(factorType, enabled, pageable);
        } else if (factorType != null) {
            return factorRepository.findByFactorType(factorType, pageable);
        } else if (enabled != null) {
            return factorRepository.findByEnabled(enabled, pageable);
        } else {
            return factorRepository.findAll(pageable);
        }
    }
    
    /**
     * 根据因子类型查找因子列表
     */
    @Transactional(readOnly = true)
    public List<Factor> findByFactorType(String factorType) {
        return factorRepository.findByFactorType(factorType);
    }
    /**
     * 根据是否启用查找因子列表
     */
    @Transactional(readOnly = true)
    public List<Factor> findByEnabled(Boolean enabled) {
        return factorRepository.findByEnabled(enabled);
    }
    /**
     * 根据因子名称模糊查询
     */
    @Transactional(readOnly = true)
    public List<Factor> findByFactorNameContaining(String factorName) {
        return factorRepository.findByFactorNameContaining(factorName);
    }
    
    /**
     * 根据因子代码模糊查询
     */
    @Transactional(readOnly = true)
    public List<Factor> findByFactorCodeContaining(String factorCode) {
        return factorRepository.findByFactorCodeContaining(factorCode);
    }

    /**
     * 启用/禁用因子
     */
    public Factor toggleFactorStatus(Long id, Boolean enabled) {
        Factor factor = factorRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("因子不存在: " + id));
        
        factor.setEnabled(enabled);
        factor.setUpdateTime(LocalDateTime.now());
        
        return factorRepository.save(factor);
    }
    /**
     * 检查因子代码是否存在
     */
    @Transactional(readOnly = true)
    public boolean existsByFactorCode(String factorCode) {
        return factorRepository.existsByFactorCode(factorCode);
    }
    /**
     * 获取所有因子（支持过滤）
     */
    @Transactional(readOnly = true)
    public List<Factor> getAllFactors(String factorType, Boolean enabled) {
        if (factorType != null && enabled != null) {
            return factorRepository.findByEnabled(enabled);
        } else if (factorType != null) {
            return factorRepository.findByFactorType(factorType);
        } else if (enabled != null) {
            return factorRepository.findByEnabled(enabled);
        } else {
            return factorRepository.findAll();
        }
    }
    /**
     * 获取所有因子（无参数版本）
     */
    @Transactional(readOnly = true)
    public List<Factor> getAllFactors() {
        return factorRepository.findAll();
    }
    /**
     * 根据ID获取因子
     */
    @Transactional(readOnly = true)
    public Factor getFactorById(Long id) {
        return factorRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("因子不存在: " + id));
    }
    /**
     * 更新因子（兼容版本）
     */
    @CacheEvict(value = "factorCache", allEntries = true)
    public Factor updateFactor(Factor factor) {
        if (factor.getId() == null) {
            throw new IllegalArgumentException("因子ID不能为空");
        }
        return updateFactor(factor.getId(), factor);
    }
    /**
     * 批量启用/禁用因子
     */
    @CacheEvict(value = "factorCache", allEntries = true)
    public List<Factor> batchToggleFactorStatus(List<Long> ids, Boolean enabled) {
        List<Factor> updatedFactors = new ArrayList<>();
        
        for (Long id : ids) {
            try {
                Factor factor = toggleFactorStatus(id, enabled);
                updatedFactors.add(factor);
            } catch (Exception e) {
                log.error("批量更新因子状态失败: {} - {}", id, e.getMessage());
            }
        }
        
        return updatedFactors;
    }
    /**
     * 统计所有因子数量
     */
    @Transactional(readOnly = true)
    public long countAllFactors() {
        return factorRepository.count();
    }
    /**
     * 根据因子类型统计数量
     */
    @Transactional(readOnly = true)
    public long countByFactorType(String factorType) {
        return factorRepository.countByFactorType(factorType);
    }
    /**
     * 根据启用状态统计数量
     */
    @Transactional(readOnly = true)
    public long countByEnabled(boolean enabled) {
        return factorRepository.countByEnabled(enabled);
    }

    public List<Factor> getFactorsByType(String type) {
        return factorRepository.findByFactorType(type);
    }
} 